package il.technion.cs236369.webserver;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ConfigParams {

	private HashMap<String,String> mimes; // ext, mime_type
	private HashMap<String, ServerHandler> handlers; // ext, handler class
	private SAXParserFactory factory;
	private SAXParser saxParser;


	/**
	 * Constructor<br>
	 * initializes the parser
	 */
	public ConfigParams(String configFilePath) {
		factory = SAXParserFactory.newInstance();
		try {
			factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,false);
			this.saxParser = factory.newSAXParser();
		} catch (ParserConfigurationException e) {
				e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
		mimes = new HashMap<String, String>();
		handlers = new HashMap<String, ServerHandler>();
		parse(configFilePath);
		factory = null;
		saxParser = null;
	}

	public String getMimeType(String extention) {
		return (String)mimes.get(extention);
	}

	public ServerHandler getServerHandler(String extention) {
		return (ServerHandler)handlers.get(extention);
	}

	private void parse(String configFilePath) {
		//validate that the file exists:
		File f = new File(configFilePath);
		if (!f.exists()) {
			throw new java.lang.IllegalArgumentException("The xml file doe's not exists");
		}

		try {
			saxParser.parse(configFilePath, new ConfigParserHandler());
		} catch (SAXException e) {
			e.printStackTrace();
			throw new java.lang.IllegalArgumentException("The xml file doe's not correct!!!!");
		} catch (IOException e) {
			e.printStackTrace();
			throw new java.lang.IllegalArgumentException("IO Exception to read xml file!!");
		}
	}


	/*
	 * =================================================================================
	 * ConfigParserHandler class
	 * =================================================================================
	 */
	class ConfigParserHandler extends DefaultHandler {

		private Boolean inHandler, inMime; // true if in the item
		ServerHandler serverHandler;
		String startElement, mimeExtension, mimeType;


		public ConfigParserHandler() {
			resetData();
		}

		public void startElement(String uri, String localName, String qName,
				Attributes attributes) throws SAXException {

			//check if this is a start element of some paper
			if (qName.equals("type-handler")) {
				inHandler = true;
				String className = attributes.getValue(0);
				serverHandler = new ServerHandler(className);
			} else if (inHandler == true && qName.equals("parameter")) {
				String propName = attributes.getValue("name");
				String propValue = attributes.getValue("value");
				serverHandler.addParameter(propName, propValue);
			} else if (qName.equals("mime-mapping")) {
				inMime = true;
			}

			startElement = qName;
		}

		public void endElement(String uri, String localName, String qName)
				throws SAXException {

			if (qName.equals("type-handler")) {
				resetData();
			}
			else if (qName.equals("mime-mapping")) {
				mimes.put(mimeExtension, mimeType);
				resetData();
			}
			startElement = null;
		}

		public void characters(char ch[], int start, int length)
				throws SAXException {
			if ((!inHandler && !inMime) || startElement == null) {
				return;
			}
			String value = new String(ch, start, length);

			if (inHandler == true && startElement.equals("extension")) {
				handlers.put(value, serverHandler);
			}

			if (inMime == true) {
				if (startElement.equals("extension")) {
					mimeExtension = value;
				} else if (startElement.equals("mime-type")) {
					mimeType = value;
				}
			}
		}

		private void resetData() {
			inHandler = false;
			inMime = false;
			serverHandler = null;
			startElement = null;
			mimeExtension = null;
			mimeType = null;
		}

	}; // ConfigParserHandler class
};
